<?php

declare(strict_types=1);

namespace App\Common\Service;

use App\Common\Constants\PayMethodConstants;
use App\Common\Constants\PayWayConstants;
use App\Common\Dto\PaymentDto;
use App\Common\Helpers\BcMath;
use App\Common\Helpers\QrCode;
use App\Common\Interfaces\PaymentInterface;
use App\CustHub\Dto\RefundDto;
use App\Setting\Service\SettingConfigService;
use Hyperf\Di\Annotation\Inject;
use Mine\Exception\NormalStatusException;
use Mine\MineRequest;
use Yansongda\HyperfPay\Pay as BigPay;
use Yansongda\Pay\Pay;

class PaymentService implements PaymentInterface
{
    #[Inject]
    protected BigPay $pay;

    #[Inject]
    protected SettingConfigService $configService;

    /**
     * 支付宝支付
     * @return \Yansongda\Pay\Provider\Alipay
     */
    public function alipay(string $notifyUrl = '', string $returnUrl = ''): \Yansongda\Pay\Provider\Alipay
    {

        $payConfig = $this->configService->getConfigByGroupKey('pay_config');
        $payConfig = array_column($payConfig, 'value', 'key');
//        // 必填-应用公钥证书 路径
//        'app_public_cert_path' => BASE_PATH.'/public/uploadfile/cert/appPublicCert.crt',
//                    // 必填-支付宝公钥证书 路径
//                    'alipay_public_cert_path' => BASE_PATH.'/public/uploadfile/cert/alipayPublicCert.crt',
//                    // 必填-支付宝根证书 路径
//                    'alipay_root_cert_path' => BASE_PATH.'/public/uploadfile/cert/alipayRootCert.crt',
        $config = [
            'alipay' => [
                'default' => [
                    // 必填-支付宝分配的 app_id
                    'app_id' => $payConfig['pay_aliay_appid'],
                    // 必填-应用私钥 字符串或路径
                    'app_secret_cert' => $payConfig['pay_alipay_app_secret_cert'],
                    // 必填-应用公钥证书 路径
                    'app_public_cert_path' => BASE_PATH . '/public' . $payConfig['pay_alipay_app_public_cert'],
                    // 必填-支付宝公钥证书 路径
                    'alipay_public_cert_path' => BASE_PATH . '/public' . $payConfig['pay_alipay_public_cert'],
                    // 必填-支付宝根证书 路径
                    'alipay_root_cert_path' => BASE_PATH . '/public' . $payConfig['pay_alipay_root_cert'],
                    'return_url' => $returnUrl,
                    'notify_url' => $notifyUrl,
                    // 选填-服务商模式下的服务商 id，当 mode 为 Pay::MODE_SERVICE 时使用该参数
                    'service_provider_id' => '',
                    // 选填-默认为正常模式。可选为： MODE_NORMAL, MODE_SANDBOX, MODE_SERVICE
                    'mode' => env('APP_ENV','dev') == 'dev' ? Pay::MODE_SANDBOX : Pay::MODE_NORMAL,
                ],
            ]
        ];
        return $this->pay->alipay(array_merge($config, ['_force' => true]));
    }

    /**
     * 微信支付
     * @return \Yansongda\Pay\Provider\Wechat
     */
    public function wechat(string $notifyUrl = ''): \Yansongda\Pay\Provider\Wechat
    {
        $payConfig = $this->configService->getConfigByGroupKey('pay_config');
        $payConfig = array_column($payConfig, 'value', 'key');

        $config = [
            'wechat' => [
                'default' => [
                    // 必填-商户号，服务商模式下为服务商商户号
                    'mch_id' => $payConfig['mch_id'],
                    'mch_secret_key_v2' => $payConfig['mch_secret_key'],
                    // 必填-商户秘钥
                    'mch_secret_key' => $payConfig['mch_secret_key'],
                    // 必填-商户私钥 字符串或路径 apiclient_key.pem这个证书文件
                    'mch_secret_cert' => BASE_PATH . '/public' . $payConfig['mch_secret_cert'],
                    // 必填-商户公钥证书路径  apiclient_cert.pem 证书文件
                    'mch_public_cert_path' => BASE_PATH . '/public' . $payConfig['mch_public_cert_path'],
                    // 必填
                    'notify_url' => $notifyUrl,
                    // 选填-公众号 的 app_id
                    'mp_app_id' => $payConfig['mp_appid'],
                    // 选填-小程序 的 app_id
//                'mini_app_id' => '',
//                // 选填-app 的 app_id
//                'app_id' => '',
                    // 选填-默认为正常模式。可选为： MODE_NORMAL, MODE_SERVICE
                    'mode' => Pay::MODE_NORMAL,
                ]
            ],
        ];
        return $this->pay->wechat(array_merge($config, ['_force' => true]));
    }


    public function unifiedPay(PaymentDto $data)
    {
        if ($data->getPayWay() == PayWayConstants::WECHAT) {
            $order = [
                'out_trade_no' => $data->getOrderNo(),
                'description' => $data->getSubject(),
                'amount' => [
                    'total' => BcMath::mul($data->getPayAmount(),100),
                ],
            ];
            try {
                $result = $this->wechat($data->getNotifyUrl())->scan($order);
                return [
                    'qr_code' => 'https://router.wikeyun.cn/qr/?text='.$result->code_url
                ];
            } catch (\Throwable $e) {
                throw new NormalStatusException('支付失败');
            }
        } elseif ($data->getPayWay() == PayWayConstants::ALIPAY) {
            $_method = $data->getPayMethod() == PayMethodConstants::WEB ? 'get' : 'post';
            $order = [
                'out_trade_no' => $data->getOrderNo(),
                'total_amount' => $data->getPayAmount(),
                'subject' => $data->getSubject(),
                'qr_pay_mode' => 4,
                'qrcode_width' => 160,
                '_method' => $_method,
            ];

            $referer = container()->get(MineRequest::class)->getHeader('referer');
            if (!empty($referer)) {
                $returnUrl = array_shift($referer);
            } else {
                $returnUrl = '';
            }

            switch ($data->getPayMethod()){
                case PayMethodConstants::WEB:
                    $url =  $this->alipay($data->getNotifyUrl(), $returnUrl)
                        ->web($order)->getHeader('Location');
                    return [
                        'url' => array_shift($url)
                    ];
                case PayMethodConstants::SCAN:
                    $result = $this->alipay($data->getNotifyUrl(), $returnUrl)
                        ->web($order);
                    return [
                        'qr_code' => $result->getBody()->getContents()
                    ];
                default:
                    throw new NormalStatusException("暂不支持当前支付方式");
            }
        } else {
            throw new NormalStatusException("暂不支持当前支付方式");
        }
    }


    public function refund(RefundDto $data)
    {
        if($data->getPayWay() == PayWayConstants::WECHAT){
            try {
                $result = $this->wechat($data->getNotifyUrl())->refund([
                    'out_trade_no' => $data->getOutTradeNo(),
                    'out_refund_no' => $data->getOutRefundNo(),
                    'amount' => [
                        'refund' => $data->getRefundAmount(),
                        'total' => $data->getTotalAmount(),
                        'currency' => 'CNY',
                    ],
                    '_action' => 'mini'
                ]);
            } catch (\Throwable $e) {
                throw new NormalStatusException('退款申请失败，请稍后重试');
            }
        }else{
            try {
                $result = $this->alipay($data->getNotifyUrl())->refund([
                    'out_trade_no' => $data->getOutTradeNo(),
                    'refund_amount' => $data->getRefundAmount(),
                    '_action' => 'scan'
                ]);
            } catch (\Throwable $e) {
                throw new NormalStatusException('退款申请失败，请稍后重试');
            }
        }
        return $result;
    }
}